<?php
	//***************************【加密解密函数】***********************************	

	//把UTF-8数据转换为GBK
	function to_gbk($str){
		return mb_convert_encoding($str,'GBK','UTF-8');
	}
	
	//把GBK数据转换为UTF-8
	function to_utf8($str){
		return mb_convert_encoding($str,'UTF-8','GBK');
	}
	
	//多次64加密函数
	function encode_64($str,$num=1){
		for($i=1;$i<=$num;$i++){
			$str=base64_encode($str);
		}
		return $str;
	}
	
	//多次64解密函数
	function decode_64($str,$num=1){
		for($i=1;$i<=$num;$i++){
			$str=base64_decode($str);
		}
		return $str;
	}
	
	// $string： 明文 或 密文  
	// $operation：DECODE表示解密,其它表示加密  
	// $key： 密匙  
	// $expiry：密文有效期  
	function authcode($string, $operation = 'DECODE', $key = '', $expiry = 0) {  
		// 动态密匙长度，相同的明文会生成不同密文就是依靠动态密匙  
		$ckey_length = 4;  
		  
		// 密匙  
		$key = md5($key ? $key : 'FEIYU');  
		  
		// 密匙a会参与加解密  
		$keya = md5(substr($key, 0, 16));  
		// 密匙b会用来做数据完整性验证  
		$keyb = md5(substr($key, 16, 16));  
		// 密匙c用于变化生成的密文  
		$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length): substr(md5(microtime()), -$ckey_length)) : '';  
		// 参与运算的密匙  
		$cryptkey = $keya.md5($keya.$keyc);  
		$key_length = strlen($cryptkey);  
		// 明文，前10位用来保存时间戳，解密时验证数据有效性，10到26位用来保存$keyb(密匙b)，解密时会通过这个密匙验证数据完整性  
		// 如果是解码的话，会从第$ckey_length位开始，因为密文前$ckey_length位保存 动态密匙，以保证解密正确  
		$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string.$keyb), 0, 16).$string;  
		$string_length = strlen($string);  
		$result = '';  
		$box = range(0, 255);  
		$rndkey = array();  
		// 产生密匙簿  
		for($i = 0; $i <= 255; $i++) {  
			$rndkey[$i] = ord($cryptkey[$i % $key_length]);  
		}  
		// 用固定的算法，打乱密匙簿，增加随机性，好像很复杂，实际上对并不会增加密文的强度  
		for($j = $i = 0; $i < 256; $i++) {  
			$j = ($j + $box[$i] + $rndkey[$i]) % 256;  
			$tmp = $box[$i];  
			$box[$i] = $box[$j];  
			$box[$j] = $tmp;  
		}  
		// 核心加解密部分  
		for($a = $j = $i = 0; $i < $string_length; $i++) {  
			$a = ($a + 1) % 256;  
			$j = ($j + $box[$a]) % 256;  
			$tmp = $box[$a];  
			$box[$a] = $box[$j];  
			$box[$j] = $tmp;  
			// 从密匙簿得出密匙进行异或，再转成字符  
			$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));  
		}  
		if($operation == 'DECODE') {  
			// substr($result, 0, 10) == 0 验证数据有效性  
			// substr($result, 0, 10) - time() > 0 验证数据有效性  
			// substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16) 验证数据完整性  
			// 验证数据有效性，请看未加密明文的格式  
			if((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26).$keyb), 0, 16)) {  
				return substr($result, 26);  
			} else {  
				return '';  
			}  
		} else {  
			// 把动态密匙保存在密文里，这也是为什么同样的明文，生产不同密文后能解密的原因  
			// 因为加密后的密文可能是一些特殊字符，复制过程可能会丢失，所以用base64编码  
			return $keyc.str_replace('=', '', base64_encode($result));  
		}  
	}
	/**************************************************************
	 *
	 *	使用特定function对数组中所有元素做处理
	 *	@param	string	&$array		要处理的字符串
	 *	@param	string	$function	要执行的函数
	 *	@return boolean	$apply_to_keys_also		是否也应用到key上
	 *	@access public
	 *
	 *************************************************************/
	function arrayRecursive(&$array, $function, $apply_to_keys_also = false)
	{
		static $recursive_counter = 0;
		if (++$recursive_counter > 1000) {
			die('possible deep recursion attack');
		}
		foreach ($array as $key => $value) {
			if (is_array($value)) {
				arrayRecursive($array[$key], $function, $apply_to_keys_also);
			} else {
				$array[$key] = $function($value);
			}
	
			if ($apply_to_keys_also && is_string($key)) {
				$new_key = $function($key);
				if ($new_key != $key) {
					$array[$new_key] = $array[$key];
					unset($array[$key]);
				}
			}
		}
		$recursive_counter--;
	}
	

	/**************************************************************
	 *
	 *	进行crypt加密
	 *	@txt	string		要加密的内容
	 *	@key    string		加密密匙
	 *
	 *************************************************************/
	function encrypt($txt,$key)   {
	    $txt = trim($txt);  
	    $iv = substr(md5($key), 0,mcrypt_get_iv_size (MCRYPT_CAST_256,MCRYPT_MODE_CFB));  
	    $c_t = mcrypt_cfb (MCRYPT_CAST_256, $key, $txt, MCRYPT_ENCRYPT, $iv);  
	    return trim(chop(base64_encode($c_t)));
	} 
	
	/**************************************************************
	 *
	 *	进行crypt解密
	 *	@txt	string		要解密的内容
	 *	@key    string		解密密匙
	 *
	 *************************************************************/
	function decrypt($txt,$key){       
	    $txt = trim(chop(base64_decode($txt)));  
	    $iv = substr(md5($key), 0,mcrypt_get_iv_size (MCRYPT_CAST_256,MCRYPT_MODE_CFB));  
	    $p_t = mcrypt_cfb (MCRYPT_CAST_256, $key, $txt, MCRYPT_DECRYPT, $iv);  
	    return trim(chop($p_t));
	}

	/**************************************************************
	 *
	 *	针对URL进行crypt加密
	 *	@txt	string		要加密的URL
	 *	@key    string		加密密匙
	 *
	 *************************************************************/
	function encrypt_url($url,$key){
	    return rawurlencode(base64_encode(encrypt($url,$key)));
	}

	/**************************************************************
	 *
	 *	针对URL进行crypt加密
	 *	@txt	string		要加密的URL
	 *	@key    string		加密密匙
	 *
	 *************************************************************/
	function decrypt_url($url,$key){
	    return decrypt(base64_decode(rawurldecode($url)),$key);
	}

	function geturl($str,$key){
	    $str = decrypt_url($str,$key);
	    $url_array = explode('&',$str);
	    if (is_array($url_array))
	    {
	        foreach ($url_array as $var)
	        {
	            $var_array = explode("=",$var);
	            $vars[$var_array[0]]=$var_array[1];
	        }
	    }
	    return $vars;
	}
?>